﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Quellenverwaltung.SRU.Exceptions;

namespace Quellenverwaltung.SRU
{
    public class Service
    {
        private Word.Configuration configuration;
        public string sruServiceUri { get; set; }
        public string sruVersion { get; set; }
        public int sruStartRecord { get; set; }
        public int sruMaximumRecords { get; set; }
        public string sruRecordSchema { get; set; }
        public string sruStylesheet { get; set; }

        public Service(String sruServiceUri)
        {
            configuration = Word.Configuration.getConfiguration();

            sruVersion = configuration.SRUServiceVersion;
            sruStartRecord = configuration.SRUServiceStartRecord;
            sruMaximumRecords = configuration.SRUServiceMaximumRecords;
            this.sruServiceUri = sruServiceUri;
        }

        public string requestSpecification()
        {
            String url = buildUri(new CQLBuilder(), "");
            string sruResult = fetchContents(url);
            return sruResult;
        }

        public string request(CQLBuilderIF cqlBuilder)
        {
            String url = buildUri(cqlBuilder, "searchRetrieve");
            string sruResult = fetchContents(url);
            return sruResult;
        }

        private string fetchContents(string url)
        {
            HttpWebRequest sruRequest = (HttpWebRequest)WebRequest.Create(url);
            sruRequest.Method = "GET";

            WebResponse sruResponse = null;
            string sruResult = "";
            try
            {
                sruResponse = sruRequest.GetResponse();
                StreamReader sr = new StreamReader(sruResponse.GetResponseStream(), System.Text.Encoding.UTF8);
                sruResult = sr.ReadToEnd();
                sr.Close();
            }
            catch (Exception ex)
            {
                throw new SRUHttpException(ex);
            }
            finally
            {
                try
                {
                    if (sruResponse != null)
                        sruResponse.Close();
                }
                catch { }
            }
            return sruResult;
        }

        private string buildUri(CQLBuilderIF cqlBuilder, string sruOperation)
        {
            String cql = cqlBuilder.getQuery();
            if (String.IsNullOrEmpty(cql)
                || String.IsNullOrEmpty(this.sruVersion))
            {
                throw new Exceptions.SRUInvalidRequestException();
            }

            String uri = this.sruServiceUri;
            uri = extendUri(uri, "operation", sruOperation);
            uri = extendUri(uri, "version", this.sruVersion);
            uri = extendUri(uri, "startRecord", this.sruStartRecord.ToString());
            uri = extendUri(uri, "maximumRecords", this.sruMaximumRecords.ToString());
            uri = extendUri(uri, "recordSchema", this.sruRecordSchema);
            uri = extendUri(uri, "stylesheet", this.sruStylesheet);

            uri += "&" + cql;
            return uri;
        }

        private string extendUri(string uri, string key, string value)
        {
            String work = uri;
            if (!String.IsNullOrEmpty(value))
            {
                if (work.Contains("?"))
                {
                    work += "&";
                }
                else
                {
                    work += "?";
                }
                work += key + "=" + Uri.EscapeDataString(value);
            }
            return work;
        }
    }
}
